﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App1AppHandler;
using System.Timers;
using Reborn_WorldServer;

namespace Reborn_Server.App1AppHandler
{
    public class Spell_Darkness : AreaSpell
    {
        public Spell_Darkness() { }

        public void PositionCast(SpellIcon _spellIcon, CreatureBase myCreatureBase, int CastLevel, int MapX, int MapY)
        {
            List<MapItem> MapItemsWithin12;
            base.InitializeInstantCast(myCreatureBase, CastLevel, _spellIcon, MapX, MapY, out MapItemsWithin12);

            //Set Duration & Damage Per Character Stats
            DurationLow = System.Convert.ToInt32((CastLevel * 1.0) + (myCreatureBase.WisdomTotal / 5.0));
            DurationHigh = System.Convert.ToInt32((CastLevel * 1.5) + (myCreatureBase.WisdomTotal / 5.0));

            MainCast(myCreatureBase, CastMapX, CastMapY, MapItemsWithin12);
        }

        public void CreatureCast(SpellIcon _spellIcon, CreatureBase myCreatureBase, int CastLevel, int MapX, int MapY)
        {
            List<MapItem> MapItemsWithin12;
            base.InitializeInstantCast(myCreatureBase, CastLevel, _spellIcon, MapX, MapY, out MapItemsWithin12);

            myCreatureBase.Mana = myCreatureBase.Mana - _spellIcon.ManaCost;
            myCreatureBase.WarmSpell = null;

            //Set Duration & Damage Per Character Stats
            DurationLow = System.Convert.ToInt32((CastLevel * 1.0) + (myCreatureBase.WisdomTotal / 5.0));
            DurationHigh = System.Convert.ToInt32((CastLevel * 1.5) + (myCreatureBase.WisdomTotal / 5.0));

            MainCast(myCreatureBase, CastMapX, CastMapY, MapItemsWithin12);
        }

        public void Cast(CreatureBase myCreatureBase, int CastLevel, List<string> MoveList)
        {
            List<MapItem> MapItemsWithin12;
            if (base.InitializeCast(myCreatureBase, CastLevel, MoveList, out MapItemsWithin12) == false)
                return;

            //Set Duration & Damage Per Character Stats
            DurationLow = System.Convert.ToInt32((CastLevel * 1.0) + (myCreatureBase.WisdomTotal / 3.0));
            DurationHigh = System.Convert.ToInt32((CastLevel * 1.5) + (myCreatureBase.WisdomTotal / 3.0));

            MainCast(myCreatureBase, CastMapX, CastMapY, MapItemsWithin12);
        }

        private void MainCast(CreatureBase myCreatureBase, int MapX, int MapY, List<MapItem> MapItemsWithin12)
        {
            List<Character> CharsInUpdateRange = new List<Character>();
            foreach (MapItem mapitem in MapItemsWithin12)
            {
                //Add this spell to each mapitem in range & record mapitem for timer
                if (mapitem.MapX - CastMapX >= -1 && mapitem.MapX - CastMapX <= 1 && mapitem.MapY - CastMapY >= -1 && mapitem.MapY - CastMapY <= 1 &&
                    mapitem.Motion > 0 && mapitem.TerrainType != "Water" && mapitem.Transparent == true)
                {
                    mapitem.SpellLayer2 = this;
                    MapItems.Add(mapitem);
                }
                foreach (CreatureBase cb in mapitem.CreaturesBases)
                {
                    if (cb is Character)
                        CharsInUpdateRange.Add((Character)cb);
                }

                //Single Tile Dark

                //if (mapitem.MapY == CastMapX && mapitem.MapY == CastMapY &&
                //    mapitem.Motion > 0 && mapitem.TerrainType != "Water" && mapitem.Transparent == true)
                //{
                //    mapitem.SpellLayer2 = this;
                //    MapItems.Add(mapitem);
                //}
            }

            //Send Updated Hexes to all characters within 8 of any hex effected
            foreach (Character character in CharsInUpdateRange)
                character.AddMapItems(MapItems, false);

            spellTimer.Interval = 3000;
            spellTimer.Start();
        }

        override protected void SpellTimer_Expired(object source, ElapsedEventArgs e)
        {
            TimerCounter = TimerCounter + 1;

            //Get MapLock
            LockItem MapLock = Managers.GameHandler.GetLockItem(MapID, Instance);
            
            //Lock MapLock
            lock (MapLock.LockObj)
            {
                //Stop Running if no mapitems
                bool FoundItem = false;
                foreach (MapItem mapitem in MapItems)
                {
                    if (mapitem.SpellLayer2.SpellID == this.SpellID)
                    {
                        FoundItem = true;
                        break;
                    }
                }
                if (FoundItem == false)
                    return;

                //Get Map
                Map CurrentMap = Managers.GameHandler.GetMap(MapID, Instance);

                List<MapItem> MapItemsToUpdate = new List<MapItem>();
                List<Character> CharsToUpdate = new List<Character>();

                foreach (MapItem mapitem in MapItems)
                {
                    if (mapitem.SpellLayer2.SpellID == this.SpellID)
                    {
                        if (TimerCounter >= DurationLow)
                        {
                            if (mapitem.MapX != CastMapX || mapitem.MapY != CastMapY)
                            {
                                int RemoveSpell = Managers.GameHandler.random.Next(-1, DurationHigh - TimerCounter);
                                if (RemoveSpell == -1)
                                {
                                    mapitem.SpellLayer2 = new Spell();
                                    MapItemsToUpdate.Add(mapitem);
                                    continue;
                                }
                            }
                            else if (TimerCounter >= DurationHigh)
                            {
                                mapitem.SpellLayer2 = new Spell();
                                MapItemsToUpdate.Add(mapitem);
                                continue;
                            }
                        }
                        //MapItemsToUpdate.Add(mapitem);
                    }
                }
                //Send Updated Hexes to all characters within 4 of any hex effected
                if (MapItemsToUpdate.Count > 0)
                {
                    //Stores all map items adjacent to any map items we're removing dark from
                    //This is used to check if hide is still valid after dark is removed
                    List<MapItem> AdjacentMapItems = new List<MapItem>();

                    foreach (MapItem mapitem in CurrentMap.MapItems)
                    {
                        foreach (MapItem mitem in MapItemsToUpdate)
                        {
                            if (Math.Abs(mitem.MapX - mapitem.MapX) <= 4 && Math.Abs(mitem.MapY - mapitem.MapY) <= 4)
                            {
                                foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                                {
                                    if (creatureBase is Character)
                                    {
                                        Character character = (Character)creatureBase;
                                        character.AddMapItems(MapItemsToUpdate, false);
                                    }
                                }
                            }

                            if (Math.Abs(mitem.MapX - mapitem.MapX) <= 1 && Math.Abs(mitem.MapY - mapitem.MapY) <= 1)
                                AdjacentMapItems.Add(mapitem);
                        }
                    }

                    //We just removed dark, check if we need to kill anyones hide spell.
                    foreach (MapItem mapitem in MapItemsToUpdate)
                    {
                        foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                        {
                            Buff hideBuff = creatureBase.buffManager.GetBuffByStackType("Hide");
                            if (hideBuff != null)
                            {
                                bool removeHide = true;

                                foreach (MapItem mItem in mapitem.mapItemsWithin4)
                                {
                                    if (Math.Abs(mItem.MapX - mapitem.MapX) <= 1 && Math.Abs(mItem.MapY - mapitem.MapY) <= 1 && mItem.TerrainUrl != "")
                                    {
                                        removeHide = false;
                                        break;
                                    }
                                }

                                if (removeHide == true)
                                    hideBuff.RemoveSpell(true, true);
                            }
                        }
                    }
                }
                
            }//End Lock

            spellTimer.Start();
        }
    }

}
